package org.jasig.cas.ext.pac4j.web.flow;

import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.ext.util.Constants;
import org.jasig.cas.support.pac4j.authentication.principal.ClientCredential;
import org.jasig.cas.web.support.WebUtils;
import org.pac4j.core.client.BaseClient;
import org.pac4j.core.client.Client;
import org.pac4j.core.client.Clients;
import org.pac4j.core.context.J2EContext;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.credentials.Credentials;
import org.pac4j.core.exception.RequiresHttpAction;
import org.pac4j.core.profile.CommonProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.context.ExternalContextHolder;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;


/**
 * 检测 OAuth 用户是否进行站内绑定 ACTION
 *
 * @author Yong.Teng <webmaster@buession.com>
 * @author rain.wen
 */
public abstract class OAuthBindCheckAction extends AbstractAction {

	/**
	 * OAuth 配置
	 */
	@NotNull
	protected Clients clients;

	protected final static Logger logger = LoggerFactory.getLogger(OAuthBindCheckAction.class);

	/**
	 * 返回 OAuth 配置
	 * 
	 * @return OAuth 配置
	 */
	public Clients getClients() {
		return clients;
	}

	/**
	 * 设置 OAuth 配置
	 * 
	 * @param clients
	 *        OAuth 配置
	 */
	public void setClients(Clients clients) {
		this.clients = clients;
	}

	/**
	 * @param context
	 *        请求上下文
	 */
	@Override
	protected Event doExecute(RequestContext context) throws Exception {
		final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
		final HttpServletResponse response = WebUtils.getHttpServletResponse(context);

		// web context
		final WebContext webContext = new J2EContext(request, response);

		// get provider type
		final String clientName = request.getParameter(this.clients.getClientNameParameter());
		logger.debug("clientName : {}", clientName);

		// it's an authentication
		if (StringUtils.isNotBlank(clientName) == true) {
			// get client
			final BaseClient<Credentials, CommonProfile> client =
					(BaseClient<Credentials, CommonProfile>) this.clients
							.findClient(clientName);
			logger.debug("client : {}", client);

			//从Spring flow 中取出用户信息
			final ClientCredential clientCredential  = (ClientCredential) context.getFlowScope().get(Constants.OAUTH_CREDENTIALS);

			if (valid(client, clientCredential) == true) {
				return success();
			}
		}

		return error();
	}

	/**
	 * 验证 OAuth 用户是否已站内绑定
	 * @param client
	 * @param clientCredential
	 * @return
	 */
	protected abstract boolean valid(final Client client,
			final ClientCredential clientCredential);

}